//其实ETCD可以被看成一个存储在线服务的数据库，只是存储但不负责提供服务，
//它的性质有点像“工商局”,它可以通知其它想要获取“服务”的应用：你想要的服务是否开放，但是工商局不负责提供服务，只是提供一个注册与通知的功能。
//由于个人设备的限制，只能将etcd服务器，服务提供者，服务请求者安置在一台云服务器上~。

//ETCD服务器，安装好之后直接运行就可以了，这还是比较简单的吧~
//  sudo apt-get install etcd   安装
//  sudo systemctl start etcd   启动
//  sudo systemctl enable etcd  开机自启动
//顺带一提ETCD的集群节点通信端口为2380,客户端访问端口为2379。
//当然这个是可以进行修改的 在/etc/default/etcd 目录下。
//这里记录一下，我没有设置开机自启动。因为鼠鼠我啊，服务器配置不太高，软件都自启动的话会拖慢速度。

//运行验证一下是否安装完毕。
//etcdctl put mykey "this is awesome" （测试）
//No help topic for 'put' （报错：可能是因为没有指定ETCD版本）
//对了！，记得指定一下ETCD的版本 export ETCDCTL_API=3
//如果没指定，指定后记得重新加载一下 source /etc/profile
//然后在执行一下测试命令》

//其实在上面的描述中，我们已经可以知道了ETCD在服务集群中是一个怎样的定位。
//可注册、可通知、可检查(这一点和ETCD的租约机制有关，一会再说~~)。

//ETCD使用
//有一个蛋疼的问题，那就是ETCD是用golang写的，但是我是C++选手啊，
//所以，去找找有没有相关的C++API~~。
//有的，有的

//ETCD——C++ API依赖安装
//sudo apt-get install libboost-all-dev libssl-dev
//sudo apt-get install libprotobuf-dev protobuf-compiler-grpc
//sudo apt-get install libgrpc-dev libgrpc++-dev
//sudo apt-get install libcpprest-dev
//ETCD——C++ API框架安装
//git clone https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3.git cd etcd-cpp-apiv3
//mkdir build
//cd build
//cmake .. -DCMAKE_INSTALL_PREFIX=/usr
//make -j$(nproc) && sudo make install          我靠，直接给哥们服务器干崩了！而且干崩了两次，换了XSHELL试了试，可以，可能VSCODE的占用量也不小


// #include <etcd/Client.hpp>
// #include <etcd/Response.hpp>
// #include <etcd/KeepAlive.hpp>
// #include <thread>
// #include <chrono>
// #include <string>

// void RegistryService(etcd::Client& etcd,const std::string& serviceKey,const std::string& serviceValue,size_t liveTime)
// {
//     // auto res_lease =  etcd.leasekeepalive(liveTime).get();
//     // int64_t leaseid =  res_lease->Lease();
//     // etcd.put(serviceKey,serviceValue,leaseid);

//     //租约获取
//     etcd::Response res = etcd.leasegrant(liveTime).get();
//     if(!res.is_ok())
//     {
//         std::cerr<<"获取响应租约失败"<<std::endl;
//     }
//     int64_t leaseid = res.value().lease();

//     //使用租约
//     etcd::Response res_service = etcd.put(serviceKey,serviceValue,leaseid).get();
//     if(!res_service.is_ok())
//     {
//         std::cerr<<"添加定时服务失败"<<std::endl;
//     }
//     //定期续约
//     int count=0;
//     while(true)
//     {   
//         etcd::KeepAlive keepalive(etcd,liveTime,leaseid);
//         //std::this_thread::sleep_for(std::chrono::seconds(liveTime/2));
//     }
//     std::this_thread::sleep_for(std::chrono::seconds(20));
//     std::cout<<"程序已退出"<<std::endl;
// }

// int main()
// {
//     try
//     {    
//         etcd::Client etcd("http://127.0.0.1:2379");
//         std::string service_name="/service";
//         std::string service_ip="127.0.0.1:8888";
//         size_t time=3; //单位：秒

//         RegistryService(etcd,service_name,service_ip,time);
//     }
//     catch(const std::exception& e)
//     {
//         std::cerr << e.what() << '\n';
//     }
//     return 0;
// }




#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <etcd/Client.hpp>
#include <etcd/Response.hpp>

// 服务提供者将服务信息注册到 ETCD 并保持活跃
void registerService(etcd::Client& etcd, const std::string& serviceKey, const std::string& serviceValue, int ttl) {
    // 创建租约
    etcd::Response leaseResp = etcd.leasegrant(ttl).get();
    if (!leaseResp.is_ok()) {
        std::cerr << "Failed to create lease. Error: " << leaseResp.error_message() << std::endl;
        return;
    }
    int64_t leaseId = leaseResp.lease_id();

    // 使用租约设置键值对
    etcd::Response setResp = etcd.set(serviceKey, serviceValue, leaseId).get();
    if (!setResp.is_ok()) {
        std::cerr << "Failed to set key-value with lease. Error: " << setResp.error_message() << std::endl;
        return;
    }
    std::cout << "Service registered with lease ID: " << leaseId << std::endl;

    // 定期续约
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(ttl / 2));
        etcd::Response keepAliveResp = etcd.leasekeepalive(leaseId).get();
        if (!keepAliveResp.is_ok()) {
            std::cerr << "Lease keep-alive failed. Error: " << keepAliveResp.error_message() << std::endl;
        } else {
            std::cout << "Lease keep-alive successful. New TTL: " << keepAliveResp.ttl() << std::endl;
        }
    }
}

int main() {
    try {
        etcd::Client etcd("http://127.0.0.1:2379");
        std::string serviceKey = "my_service";
        std::string serviceValue = "127.0.0.1:8080";
        int ttl = 10; // 租约时间（秒）

        registerService(etcd, serviceKey, serviceValue, ttl);
    } catch (const std::exception& e) {
        std::cerr << "Exception occurred: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}    